﻿using Microsoft.Win32.SafeHandles;
using Serilog;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace PinusClientDemo.Tools
{
    public class LogHelper
    {
        #region DllImport -- 注册
        [DllImport("kernel32.dll",
            EntryPoint = "AllocConsole",
            SetLastError = true,
            CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall)]
        private static extern int AllocConsole();

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr CreateFile(
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            uint lpSecurityAttributes,
            uint dwCreationDisposition,
            uint dwFlagsAndAttributes,
            uint hTemplateFile);

        private const int MY_CODE_PAGE = 437;
        private const uint GENERIC_WRITE = 0x40000000;
        private const uint FILE_SHARE_WRITE = 0x2;
        private const uint OPEN_EXISTING = 0x3;

        [DllImport("kernel32.dll")]
        public static extern Boolean FreeConsole();

        [DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll ", EntryPoint = "GetSystemMenu")]
        static extern IntPtr GetSystemMenu(IntPtr hWnd, IntPtr bRevert);
        [DllImport("user32.dll ", EntryPoint = "RemoveMenu")]
        static extern int RemoveMenu(IntPtr hMenu, int nPos, int flags);
        #endregion

        private static bool _initialized;
        private static object _lockObject;

        private static ILogger _logger;

        static LogHelper()
        {
            _initialized = false;
            _lockObject = new object();
        }

        private static void Initialize()
        {
            if (!_initialized)
            {
                lock (_lockObject)
                {
                    if (!_initialized)
                    {
                        _logger = new LoggerConfiguration().WriteTo.Console().CreateLogger();
                        _initialized = true;
                    }
                }
            }
        }

        public static ILogger Log
        {
            get
            {
                Initialize();
                return _logger;
            }
        }

        public static void CreateConsole()
        {
            AllocConsole();

            IntPtr stdHandle = CreateFile(
                "CONOUT$",
                GENERIC_WRITE,
                FILE_SHARE_WRITE,
                0, OPEN_EXISTING, 0, 0
            );

            SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
            FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write); 
            Encoding encoding = System.Text.Encoding.Default;
            StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
            standardOutput.AutoFlush = true; 
            Console.SetOut(standardOutput);

            int WINDOW_HANDLER = FindWindow(null, Console.Title);

            IntPtr CLOSE_MENU = GetSystemMenu((IntPtr)WINDOW_HANDLER, IntPtr.Zero);
            int SC_CLOSE = 0xF060;
            RemoveMenu(CLOSE_MENU, SC_CLOSE, 0x0);
        }

        public static void CloseConsole() => FreeConsole();
    }
}